// createStore(reducer,payloadState,enhancer)
// {getStore,dispatch,subscribe}


function createStore(reducer, payloadState, enhancer) {
    // 约束reducer参数类型
    if (typeof reducer !== "function") throw new Error("reducer必须是函数")
    // 判断 enhancer有没有传参
    if (typeof enhancer !== 'undefined') {
        // 判断 enhancer是不是一个函数
        if (typeof enhancer !== 'function') {
            throw new Error("enhancer必须是函数")
        }
        return enhancer(createStore)(reducer, payloadState)
    }
    // store对象中初始状态
    let currentStore = payloadState;
    // 存放订阅者函数
    let currentCallBack = []
    // 获取store中的状态
    function getStore() {
        return currentStore
    }
    // 触发 action
    function dispatch(action) {
        console.log(action)

        // 判断action是否是对象
        if (!isPlainObject(action)) throw new Error("action必须是对象")
        // 判断action对象是否具有type属性
        if (typeof action.type === "undefined") throw new Error("action对象中必须有type属性")
        currentStore = reducer(currentStore, action)
        // 循环数组订阅者
        for (var i = 0; i < currentCallBack.length; i++) {
            // 获取订阅者
            var callback = currentCallBack[i]
            // 调用订阅者
            callback()
        }
    }
    // 订阅状态
    function subscribe(callback) {
        currentCallBack.push(callback)
    }
    return {
        getStore,
        dispatch,
        subscribe
    }
}

function isPlainObject(action) {
    //  排除基本数据类型和null
    if (typeof action !== "object" || typeof action === null) return false
    var proto = action
    while (Object.getPrototypeOf(proto) != null) {
        proto = Object.getPrototypeOf(proto)
    }
    return Object.getPrototypeOf(action) === proto
}

function applyMiddleware(...middlewares) {
    return function (createStore) {
        return function (reducer, payloadState) {
            //    创建store
            let store = createStore(reducer, payloadState)
            //   简约版 store
            let middlewareAPI = {
                getStore: store.getStore,
                dispatch: store.dispatch
            }
            // 调用中间件的第一层函数，传递简约版的store对象
            let chain = middlewares.map(middleware => middleware(middlewareAPI))
           let dispatch =  compose(chain)(store.dispatch)
           return {
               ...store,
               dispatch
           }
        }
    }
}

function compose(chain) {
    return function (dispatch) {
        for (var i = chain.length - 1; i >= 0; i--) {
            dispatch = chain[i](dispatch)
        }
        return dispatch
    }
}

function bindActionCreators(actionCreators,dispatch) { 
   var boundActionCreators = {}
   for(var key in actionCreators){
       (function(key){
        boundActionCreators[key] = function(){
            dispatch(actionCreators[key]())
        }
       })(key)
   }
   console.log(boundActionCreators)
   return boundActionCreators
}

function combineReducers(reducers){
    // 判断reducer是否是函数
    let reducerKey = Object.keys(reducers)
    for(var i=0;i<reducerKey.length;i++){
        let key = reducerKey[i]
        if(typeof reducers[key] !== 'function') throw new Error("reducers必须是函数")
    }
    return function (state,action){
        let nextState = {}
        for(var i=0;i<reducerKey.length;i++){
            let key = reducerKey[i]
            let reducer = reducers[key]
            let preState = state[key]
            nextState[key] = reducer(preState,action)
            console.log(nextState)
        }
        return nextState
    }
}
